package org.libermundi.theorcs.core.dao.hibernate;

import java.io.Serializable;
import java.util.List;

import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Order;
import org.libermundi.theorcs.core.dao.GenericDao;
import org.libermundi.theorcs.core.model.base.Activable;
import org.libermundi.theorcs.core.model.base.Identifiable;
import org.libermundi.theorcs.core.model.base.Undeletable;

public interface HibernateDao<T extends Identifiable<I>, I extends Serializable> extends GenericDao<T, I> {
    /**
     * Create a Criteria object based-on the entity of DAO
     *
     */
    Criteria createSimpleCriteria();

    /**
     * Create a Criteria object based-on the entity of DAO.
     * Is Entity implements {@link Undeletable} or {@link Activable}
     * makes sure that they are taken in account
     *
     */
    Criteria createSafeCriteria();
    
    /**
     * Allow to get a Query object when Criteria is not enought
     * 
     */
    Query createQuery(String hqlQuery);
    
    /**
     * Retrieve objects using criteria.
     *
     * @param criteria criteria which will be executed
     * @return list of founded objects
     * @see javax.persistence.Query#getResultList()
     */
    List<T> findByCriteria(Criteria criteria);
    
    /**
     * Retrieve an unique object using criteria. It is equivalent to <code>criteria.uniqueResult(_entityManager)</code>.
     *
     * @param criteria criteria which will be executed
     * @return retrieved object
     * @throws NoResultException - if there is no result
     * @throws NonUniqueResultException - if more than one result
     * @see javax.persistence.Query#getSingleResult()
     */
    T findUniqueByCriteria(Criteria criteria) throws NonUniqueResultException, NoResultException;

    /**
    * 
    * Default order 
    *  
    * @return Order
    * 
    */
    Order getDefaultOrder();
    
    T find(Class<T> type,I primaryKey);
}
